package cc.verywell.pureblock.util.sign;

import java.nio.ByteBuffer;
import java.security.DigestException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import cc.verywell.pureblock.log.Pblog;
import cc.verywell.pureblock.util.HashUtil;

/**
* 
* https://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest
*
* @author TanYaqiu 
* @address flat 601
* @date 2019年2月25日 上午12:07:33
*/
public class Sha implements HashUtil {
	
	private final MessageDigest messageDigest;
	public Sha() {
		this("SHA-256");
	}
	protected Sha(String algorithm) {
		try {
			messageDigest = MessageDigest.getInstance(algorithm);
		} catch (NoSuchAlgorithmException e) {
			if(Pblog.INIT)Pblog.INIT(e);
			throw new RuntimeException(e);
		}
	}
	
	public final byte[] hash(byte[] src) {
		try {
			return messageDigest.digest(src);
		}finally{
			messageDigest.reset();
		}
	}
	public final byte[] hash(ByteBuffer bb) {
		try {
			messageDigest.update(bb.array(),bb.position()+bb.arrayOffset(),bb.remaining());
			return messageDigest.digest();
		}finally{
			messageDigest.reset();
		}
	}
	public final void hash(byte[] bb,byte[] out) throws DigestException {
		try {
			messageDigest.update(bb,0,bb.length);
			messageDigest.digest(out,0,out.length);
			//bb.position(bb.limit());
			//return result;
		}finally{
			messageDigest.reset();
		}
	}

	public final void hash(ByteBuffer bb,byte[] out) throws DigestException {
		try {
			messageDigest.update(bb.array(),bb.position()+bb.arrayOffset(),bb.remaining());
			messageDigest.digest(out,0,out.length);
			//bb.position(bb.limit());
			//return result;
		}finally{
			messageDigest.reset();
		}
	}
	@Override
	final public int length() {
		return messageDigest.getDigestLength();
	}
	
	//////////////////////
	static private ThreadLocal<Sha> ins = new ThreadLocal<Sha>() {
		@Override
		protected Sha initialValue() {
			return new Sha();
		}
	};
	static public Sha getInstance() {
		return ins.get();
	}

}
